package com.yunchao.library.socket.utils

import java.nio.ByteBuffer
import java.nio.ByteOrder

object ConvertUtils {


    /**
     * 将字符串转换为 Ln-V 格式的字节数组
     * @param str 输入字符串（允许为空）
     * @param lengthBytes 长度字段的字节数（1、2、4）
     * @throws IllegalArgumentException 如果长度字段不足以容纳字符串长度
     */
    fun stringToLn(str: String?, lengthBytes: Int = 4): ByteArray {
        // 处理 null 或空字符串
        val value = str ?: ""
        val utf8Bytes = value.toByteArray(Charsets.UTF_8)
        val length = utf8Bytes.size

        // 校验长度是否超出 Ln 的表示范围
        when (lengthBytes) {
            1 -> require(length <= 0xFF) { "String length exceeds U1 (255 bytes)" }
            2 -> require(length <= 0xFFFF) { "String length exceeds U2 (65535 bytes)" }
            4 -> {} // U4 可表示 2^32-1，无需校验
            else -> throw IllegalArgumentException("lengthBytes must be 1, 2, or 4")
        }

        // 分配缓冲区（Ln + V）
        val buffer = ByteBuffer.allocate(lengthBytes + length)
            .order(ByteOrder.BIG_ENDIAN) // 规范要求网络字节序（Big-Endian）

        // 写入长度字段（Ln）
        when (lengthBytes) {
            1 -> buffer.put(length.toByte())
            2 -> buffer.putShort(length.toShort())
            4 -> buffer.putInt(length)
        }

        // 写入字符串数据（V）
        buffer.put(utf8Bytes)

        return buffer.array()
    }


    /**
     * 读取 Ln-V 格式的字符串
     * @param bytes 源数据（必须完整包含 Ln 和 V）
     * @param lengthBytes 长度字段的字节数（1、2、4）
     * @throws IllegalArgumentException 如果输入不合法
     */
    fun lnVToString(bytes: ByteArray, lengthBytes: Int = 4): String {
        require(bytes.isNotEmpty()) { "Input bytes cannot be empty" }

        val buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN)

        // 1. 读取长度字段
        val length = when (lengthBytes) {
            1 -> buffer.get().toInt() and 0xFF     // U1（无符号）
            2 -> buffer.short.toInt() and 0xFFFF    // U2
            4 -> buffer.int                         // U4
            else -> throw IllegalArgumentException("lengthBytes must be 1, 2, or 4")
        }

        // 2. 校验剩余数据是否足够
        require(buffer.remaining() >= length) {
            "Malformed Ln-V data: expected $length bytes, but only ${buffer.remaining()} available"
        }

        // 3. 读取数据（允许 length=0）
        val valueBytes = ByteArray(length)
        if (length > 0) {
            buffer.get(valueBytes)
        }

        return String(valueBytes, Charsets.UTF_8)
    }

    // 检查n的合法性
    private fun checkN(n: Int) {
        require(n in setOf(1, 2, 4)) { "n must be 1, 2, or 4" }
    }

    //region 字节数组与十六进制字符串转换
    /**
     * 将字节数组转换为十六进制字符串
     * @param uppercase 是否使用大写字母，默认为true
     * @return 十六进制字符串，例如 "416263" 表示 [65, 98, 99]
     */
    fun ByteArray.toByteArrayHexString(uppercase: Boolean = true): String {
        val format = if (uppercase) "%02X" else "%02x"
        return joinToString("") { String.format(format, it) }
    }

    /**
     * 将十六进制字符串转换为字节数组
     * @return 对应的字节数组
     * @throws IllegalArgumentException 如果字符串不是有效的十六进制格式
     */
    fun String.hexStringToByteArray(): ByteArray {
        require(length % 2 == 0) { "Hex string must be even length" }
        return chunked(2)
            .map { it.toInt(16).toByte() }
            .toByteArray()
    }
    //endregion

    //region 字节数组与二进制字符串转换
    /**
     * 将字节数组转换为二进制字符串
     * 每个字节转换为8位二进制字符串，不足8位时在左侧补0
     */
    fun ByteArray.toBinaryString(): String = this.joinToString("") {
        String.format("%8s", Integer.toBinaryString(it.toInt() and 0xFF)).replace(' ', '0')
    }

    /**
     * 将二进制字符串转换为字节数组
     * @return 对应的字节数组
     */
    fun String.binaryToByteArray(): ByteArray {
        require(this.all { it in '0'..'1' }) { "Invalid binary string" }
        val byteCount = (this.length + 7) / 8

        return ByteArray(byteCount) { index ->
            val start = index * 8
            val end = minOf(start + 8, this.length)
            val byteBinary = this.substring(start, end).padStart(8, '0')
            byteBinary.toInt(2).toByte()
        }
    }
    //endregion

    //region Int与字节数组转换
    /**
     * 将int转换为4字节的字节数组（大端序）
     */
    fun intToByteArray(value: Int): ByteArray {
        return byteArrayOf(
            (value shr 24).toByte(),
            (value shr 16).toByte(),
            (value shr 8).toByte(),
            value.toByte()
        )
    }

    /**
     * 将字节数组转换为int（大端序）
     */
    fun byteArrayToInt(bytes: ByteArray): Int {
        var result = 0
        for (i in 0 until minOf(bytes.size, 4)) {
            result = (result shl 8) or (bytes[i].toInt() and 0xFF)
        }
        return result
    }
    //endregion

    //region 无符号整数解析
    /**
     * 从字节数组中解析无符号Byte（U1）
     * @return 解析后的无符号值（范围：0-255）
     */
    fun parseUnsignedByte(bytes: ByteArray, offset: Int = 0): UShort =
        (bytes[offset].toInt() and 0xFF).toUShort()

    /**
     * 从字节数组中解析无符号Short（U2）
     * @return 解析后的无符号值（范围：0-65535）
     */
    fun parseUnsignedShort(bytes: ByteArray, offset: Int = 0): UShort =
        ((bytes[offset].toInt() and 0xFF) shl 8 or
                (bytes[offset + 1].toInt() and 0xFF)).toUShort()

    /**
     * 从字节数组中解析无符号Int（U4）
     * @return 解析后的无符号值（范围：0-4294967495）
     */
    fun parseUnsignedInt(bytes: ByteArray, offset: Int = 0): UInt =
        ((bytes[offset].toLong() and 0xFF) shl 24 or
                (bytes[offset + 1].toLong() and 0xFF) shl 16 or
                (bytes[offset + 2].toLong() and 0xFF) shl 8 or
                (bytes[offset + 3].toLong() and 0xFF)).toUInt()

    /**
     * 从字节数组中解析无符号Long（U8）
     * @return 解析后的无符号值（范围：0-18446744073709551615）
     */
    fun parseUnsignedLong(bytes: ByteArray, offset: Int = 0): ULong {
        require(offset + 8 <= bytes.size) { "Buffer underflow" }
        return (bytes[offset].toLong() and 0xFF shl 56 or
                (bytes[offset + 1].toLong() and 0xFF shl 48) or
                (bytes[offset + 2].toLong() and 0xFF shl 40) or
                (bytes[offset + 3].toLong() and 0xFF shl 32) or
                (bytes[offset + 4].toLong() and 0xFF shl 24) or
                (bytes[offset + 5].toLong() and 0xFF shl 16) or
                (bytes[offset + 6].toLong() and 0xFF shl 8) or
                (bytes[offset + 7].toLong() and 0xFF)).toULong()
    }
    //endregion

    //region 无符号整数转字节数组
    /**
     * 将无符号Byte（U1）转换为字节数组
     */
    fun u1ToByteArray(value: UByte): ByteArray {
        return byteArrayOf(value.toByte())
    }

    /**
     * 将无符号Short（U2）转换为字节数组（大端序）
     */
    fun u2ToByteArray(value: UShort): ByteArray {
        val intValue = value.toUInt()  // 转换为UInt进行位操作
        return byteArrayOf(
            ((intValue shr 8) and 0xFFu).toByte(),  // 高8位
            (intValue and 0xFFu).toByte()           // 低8位
        )
    }

    /**
     * 将无符号Int（U4）转换为字节数组（大端序）
     */
    fun u4ToByteArray(value: UInt): ByteArray {
        return byteArrayOf(
            ((value shr 24) and 0xFFu).toByte(),
            ((value shr 16) and 0xFFu).toByte(),
            ((value shr 8) and 0xFFu).toByte(),
            (value and 0xFFu).toByte()
        )
    }

    /**
     * 将无符号Long（U8）转换为字节数组（大端序）
     */
    fun u8ToByteArray(value: ULong): ByteArray {
        return byteArrayOf(
            ((value shr 56) and 0xFFuL).toByte(),
            ((value shr 48) and 0xFFuL).toByte(),
            ((value shr 40) and 0xFFuL).toByte(),
            ((value shr 32) and 0xFFuL).toByte(),
            ((value shr 24) and 0xFFuL).toByte(),
            ((value shr 16) and 0xFFuL).toByte(),
            ((value shr 8) and 0xFFuL).toByte(),
            (value and 0xFFuL).toByte()
        )
    }
    //endregion

    //region Ln-V 编码处理
    /**
     * 解析Ln-V类型（长度-值编码）
     * @param bytes 输入的字节数组
     * @param n 长度字段的字节数（1、2或4）
     * @return 解析后的值的字节数组
     */
    fun parseLnV(bytes: ByteArray, n: Int): ByteArray {
        checkN(n)
        if (bytes.isEmpty()) throw IllegalArgumentException("Input bytes cannot be empty")
        if (bytes.size < n) throw IllegalArgumentException("Input bytes too short for n=$n")

        // 读取长度字段
        val length = when (n) {
            1 -> parseUnsignedByte(bytes, 0).toInt()
            2 -> parseUnsignedShort(bytes, 0).toInt()
            4 -> parseUnsignedInt(bytes, 0).toInt()
            else -> throw IllegalArgumentException("Invalid n value: $n") // 前面已验证，不会到达此分支
        }

        // 读取值字段
        val valueStartIndex = n
        if (valueStartIndex + length > bytes.size) {
            throw IllegalArgumentException("Input bytes are too short for specified length, actual length: ${bytes.size}, expected at least: $valueStartIndex + $length")
        }
        return bytes.copyOfRange(valueStartIndex, valueStartIndex + length)
    }

    /**
     * 构建Ln-V类型（长度-值编码）
     * @param value 要编码的值的字节数组
     * @param n 长度字段的字节数（1、2或4）
     * @return 编码后的字节数组
     */
    private fun buildLnV(value: ByteArray, n: Int): ByteArray {
        checkN(n)

        // 检查值的长度是否适合所选的 n
        val maxLength = when (n) {
            1 -> 0xFFuL  // 使用ULong类型表示无符号值
            2 -> 0xFFFFuL
            4 -> 0xFFFFFFFFuL
            else -> throw IllegalArgumentException("Invalid n value: $n")
        }

        if (value.size.toULong() > maxLength) {
            throw IllegalArgumentException("Value too large for specified n=$n, value length: ${value.size}, max allowed length: $maxLength")
        }

        // 创建长度字段的字节数组
        val lengthBytes = when (n) {
            1 -> u1ToByteArray(value.size.toUByte())
            2 -> u2ToByteArray(value.size.toUShort())
            4 -> u4ToByteArray(value.size.toUInt())
            else -> throw IllegalArgumentException("Invalid n value: $n") // 前面已验证，不会到达此分支
        }

        // 合并长度字段和值字段
        return lengthBytes + value
    }
    //endregion


    //region String 类型 一个 L4-V 编码的数据，V 为 UTF-8 编码的字符串数据
    /**
     * 解析L4-V编码的UTF-8字符串
     * @param bytes 输入的字节数组（包含4字节长度+UTF-8字符串）
     * @return 解码后的字符串
     */
    fun parseL4VString(bytes: ByteArray): String {
        val valueBytes = parseLnV(bytes, 4) // 使用n=4调用LnV解析方法
        return String(valueBytes, Charsets.UTF_8) // 将字节数组按UTF-8编码转换为字符串
    }

    /**
     * 构建L4-V编码的UTF-8字符串
     * @param str 要编码的字符串
     * @return L4-V编码的字节数组（4字节长度+UTF-8字符串）
     */
    fun buildL4VString(str: String): ByteArray {
        val valueBytes = str.toByteArray(Charsets.UTF_8) // 将字符串按UTF-8编码转换为字节数组
        return buildLnV(valueBytes, 4) // 使用n=4调用LnV构建方法
    }
    //endregion


    //region 字节数组合并
    /**
     * 合并多个字节数组
     */
    fun byteMergerAll(vararg values: ByteArray): ByteArray {
        val totalSize = values.sumOf { it.size }
        if (totalSize == 0) return byteArrayOf()

        return ByteArray(totalSize).apply {
            var offset = 0
            values.forEach { src ->
                src.copyInto(this, offset)
                offset += src.size
            }
        }
    }
    //endregion

    //region L8V格式处理（8字符长度+数据）
    /**
     * 解析L8V格式数据（前8个字符为长度，后续为字符串数据）
     * @param input 包含L8V格式数据的字符串
     * @return 解析后的字符串，若数据不足则返回null
     */
    fun parseL8VData(input: String): String? {
        if (input.length < 8) return null

        val lengthStr = input.substring(0, 8).trimStart('0')
        val length = if (lengthStr.isEmpty()) 0 else lengthStr.toInt()

        if (input.length < 8 + length) return null
        return input.substring(8, 8 + length)
    }
    //endregion


    /**
     * 将 ByteArray 中指定范围的字节替换为0
     * @param source 源字节数组
     * @param startIndex 起始索引（包含）
     * @param endIndex 结束索引（包含）
     * @return 替换后的新字节数组
     */
    fun replaceRangeWithZero(source: ByteArray, startIndex: Int, endIndex: Int): ByteArray {
        require(startIndex >= 0 && startIndex <= endIndex && endIndex < source.size) {
            "Invalid range: startIndex=$startIndex, endIndex=$endIndex, array size=${source.size}"
        }

        val result = source.copyOf()  // 创建副本，避免修改原数组
        for (i in startIndex..endIndex) {
            result[i] = 0
        }
        return result
    }
}